/**
 * @(#)SuperShot.java
 *
 *
 * @author 
 * @version 1.00 2010/2/2
 */

import java.util.*;
import java.awt.geom.*;

public class SuperShot extends Shot
{
	public enum SuperType
	{
		INVINCIBLE, HOMING, PERFECT_HOMING, WRAP_AROUND, EXPLOSIVE, CHAIN_REACTION, SELF_HOMING
	}
	private boolean[] shot_qualities;
	private Rock target;
	public static final double MAX_OMEGA = (Ship.PI)/20;
	public static final int EXPLOSION_SIZE = 20;

    public SuperShot(double newHeading, double startX, double startY, double velocity, SuperType[] new_shot_qualities) 
    {
    	super(newHeading, startX, startY, velocity);
    	shot_qualities = new boolean[SuperType.values().length];
    	for(int i = 0; i < shot_qualities.length; i++)
    	{
    		shot_qualities[i] = false;
    	}
    	for(int i = 0; i < new_shot_qualities.length; i++)
    	{
    		shot_qualities[new_shot_qualities[i].ordinal()] = true;
    	}
    }
    public SuperShot(double newHeading, double startX, double startY, double velocity, boolean[] new_shot_qualities) 
    {
    	super(newHeading, startX, startY, velocity);
    	shot_qualities = new boolean[new_shot_qualities.length];
    	for(int i = 0; i < shot_qualities.length; i++)
    	{
    		shot_qualities[i] = new_shot_qualities[i];
    	}
    }	
    
    public boolean IsInvincible()
    {
    	return shot_qualities[SuperShot.SuperType.INVINCIBLE.ordinal()];
    }
    
    public void Update()
    {
    	if(shot_qualities[SuperShot.SuperType.HOMING.ordinal()]||
    			shot_qualities[SuperShot.SuperType.PERFECT_HOMING.ordinal()]||
    			shot_qualities[SuperShot.SuperType.SELF_HOMING.ordinal()])
    	{
    		//System.out.println(target);	
    		//if(target == null)
    		//{
    		
    		target=AcquireTarget(Asteroids.GetRocks());	
    		//}
    		
    		Point2D.Double target_position = (shot_qualities[SuperShot.SuperType.SELF_HOMING.ordinal()])? 
    				Asteroids.GetShipPosition() :target.GetPosition();
    		//double target_angle = Math.atan((xPosition - target_position.getX())/(target_position.getY() - yPosition));
    		double target_angle;
    		//if(target_position.getY() == yPosition)
    		//{
    		//	target_angle = Ship.PI/2;
    		//}
    		if(target_position.getY() < yPosition)
    		{
    			target_angle = Math.atan((xPosition - target_position.getX())/(target_position.getY() - yPosition));
    			if(target_angle - heading > Ship.PI)
    			{
    				heading += (shot_qualities[SuperShot.SuperType.PERFECT_HOMING.ordinal()])?
        				target_angle - heading : -Limit(target_angle-heading, -MAX_OMEGA, MAX_OMEGA);
    				//System.out.println("1");
    			}
    			else
    			{
    				heading += (shot_qualities[SuperShot.SuperType.PERFECT_HOMING.ordinal()])?
    				target_angle - heading : Limit(target_angle-heading, -MAX_OMEGA, MAX_OMEGA);
    				//System.out.println("2");
    			}
    		}
    		else
    		{
    			target_angle = Math.atan((xPosition - target_position.getX())/(target_position.getY() - yPosition)) - Ship.PI;
    			if(target_angle - heading > Ship.PI)
    			{
    				heading += (shot_qualities[SuperShot.SuperType.PERFECT_HOMING.ordinal()])?
        				target_angle - heading : -Limit(target_angle-heading, -MAX_OMEGA, MAX_OMEGA);
    				//System.out.println("3");
    			}
    			else
    			{
    				heading += (shot_qualities[SuperShot.SuperType.PERFECT_HOMING.ordinal()])?
    				target_angle - heading : Limit(target_angle-heading, -MAX_OMEGA, MAX_OMEGA);
    				//System.out.println("4");
    			}
    		}
    		
    		//System.out.println(target_position.getY() + " "  + target_position.getX() + " " + target + " " + xPosition + " " + yPosition);
    		//heading+=target_angle - heading;
    		
    		//System.out.println(heading);
    		xVelocity=velocity*Math.sin(heading);
    		yVelocity=velocity*Math.cos(heading);
    	
    		
    	}
    	//else
    	//{
	    	super.Update();
	    	if(shot_qualities[SuperShot.SuperType.WRAP_AROUND.ordinal()])
	    	{
	   			if(xPosition < 0)
		    	{
		    		xPosition += AsteroidsFrame.FRAME_WIDTH;
		    	}
		    	else if(xPosition > AsteroidsFrame.FRAME_WIDTH)
		    	{
		    		xPosition -= AsteroidsFrame.FRAME_WIDTH;
		    	}
		    	
		    	if(yPosition < 0)
		    	{
		    		yPosition += AsteroidsFrame.FRAME_HEIGHT;
		    	}
		    	else if(yPosition > AsteroidsFrame.FRAME_HEIGHT)
		    	{
		    		yPosition -= AsteroidsFrame.FRAME_HEIGHT;
		    	}
		    	shotShape = new Line2D.Double(xPosition - LENGTH * Math.sin(heading), yPosition + LENGTH * Math.cos(heading), xPosition, yPosition);
	    	//}
    	}
    	
    }
    
    public Rock AcquireTarget(Rock[] legal_targets)
    {
    	double closest_distance = 1000;
    	int closest_rock = 0;
    	
    	for(int i = 0; i < legal_targets.length; i++)
    	{
    		double dist = this.getPositionPoint().distance(legal_targets[i].GetPosition());
    		if(dist < closest_distance)
    		{
    			closest_distance = dist;
    			closest_rock = i;
    		}
    	}
    	return legal_targets[closest_rock];
    }
    public double Limit(double init_value, double bottom_limit, double top_limit)
    {
    	if(init_value > top_limit)
    	{
    		return top_limit;
    	}
    	else if(init_value < bottom_limit)
    	{
    		return bottom_limit;
    	}
    	else
    	{
    		return init_value;
    	}
    }
	
	public void ShotSomething(ArrayList<SuperShot> super_list)
	{
		if(shot_qualities[SuperShot.SuperType.EXPLOSIVE.ordinal()] || shot_qualities[SuperShot.SuperType.CHAIN_REACTION.ordinal()] && Asteroids.GetNumShots() < AsteroidsFrame.SHOT_LIMIT)
		{
			SuperShot[] explosion_shots = Explode();
			for(int i = 0; i < EXPLOSION_SIZE; i++)
			{
				super_list.add(explosion_shots[i]);
			}
		}
	}
	
	private SuperShot[] Explode()
	{
		SuperShot[] return_shots = new SuperShot[EXPLOSION_SIZE];
		shot_qualities[SuperShot.SuperType.EXPLOSIVE.ordinal()] = false;
		for(int i = 0; i < EXPLOSION_SIZE; i++)
    	{
    		return_shots[i] = new SuperShot(heading + 2*Ship.PI*i/EXPLOSION_SIZE, xPosition, yPosition, velocity, shot_qualities);
    	}
    	shot_qualities[SuperShot.SuperType.INVINCIBLE.ordinal()] = false;
    	return return_shots;
	}
    
}